


// 判断当前配置使用使用了 ExtractTextPlugin，
// compiler 参数即为 Webpack 在 apply(compiler) 中传入的参数
function hasExtractTextPlugin(compiler) {

    // 当前配置所有使用的插件列表
    const plugins = compiler.options.plugins;

    // 去 plugins 中寻找有没有 ExtractTextPlugin 的实例
    return plugins.find( plugin=> {

        // console.log('plugin.__proto__.constructor',plugin.__proto__.constructor);
        
        return plugin.__proto__.constructor.toString() === 'UglifyJsPlugin'

    }) != null;
}

class test{

    // 在构造函数中获取用户给该插件传入的配置
    constructor(options){

        console.log('\n\n插件开始执行  --------->\n\n');
        
    }

    // Webpack 会调用 test 实例的 apply 方法给插件实例传入 compiler 对象
    apply(compiler){

        /***
         *
         * 初始化阶段
         *
         */

        //  开始应用 Node.js 风格的文件系统到 compiler 对象，以方便后续的文件寻找和读取
        compiler.hooks.environment.tap('test1',(stats) => {

            console.log('\n\environment --------->\n\n');

        });

        // 读取配置的 Entrys，为每个 Entry 实例化一个对应的 EntryPlugin，为后面该 Entry 的递归解析工作做准备。
        compiler.hooks.entryOption.tap('test',(stats) => {

            console.log('\n\nentryOption --------->\n\n');

        });

        // 调用完所有内置的和配置的插件的 apply 方法。
        compiler.hooks.afterPlugins.tap('test',(stats) => {

            console.log('\n\afterPlugins --------->\n\n');

        });

        // 根据配置初始化完 resolver，resolver 负责在文件系统中寻找指定路径的文件。
        compiler.hooks.afterResolvers.tap('test',(stats) => {

            console.log('\n\afterResolvers --------->\n\n');

        });


        /***
         *
         * 编译阶段
         *
         */

        //  启动一次新的编译。
        compiler.hooks.run.tap('test',(stats) => {

            console.log('\n\nrun --------->\n\n');

        });

        // 和 run 类似，区别在于它是在监听模式下启动的编译，在这个事件中可以获取到是哪些文件发生了变化导致重新启动一次新的编译。
        compiler.hooks.watchRun.tap('test',(stats) => {

            console.log('\n\nwatchRun --------->\n\n');

        });

        //  该事件是为了告诉插件一次新的编译将要启动，同时会给插件带上 compiler 对象。
        compiler.hooks.compile.tap('test',(stats) => {

            console.log('\n\ncompile --------->\n\n');

        });

        // 当 Webpack 以开发模式运行时，每当检测到文件变化，一次新的 Compilation 将被创建。
        // 一个 Compilation 对象包含了当前的模块资源、编译生成资源、变化的文件等。Compilation 对象也提供了很多事件回调供插件做扩展。
        
        compiler.hooks.compilation.tap('test',(compilation) => {

            compilation.seal(function(){
                console.log('\n\seal --------->\n\n');
            })

            // compilation.buildModule(function(){
            //     console.log('\n\seal --------->\n\n');
            // })

            // compilation.program(function(){
            //     console.log('\n\seal --------->\n\n');
            // })

            // compilation.normalModuleLoader(function(){
            //     console.log('\n\seal --------->\n\n');
            // })

        });

        // 一个新的 Compilation 创建完毕，即将从 Entry 开始读取文件，根据文件类型和配置的 Loader 对文件进行编译，
        // 编译完后再找出该文件依赖的文件，递归的编译和解析。
        compiler.hooks.make.tap('test',(stats) => {

            console.log('\n\make --------->\n\n');

        });

        // 一次 Compilation 执行完成
        compiler.hooks.afterCompile.tap('test',(stats) => {

            console.log('\n\afterCompile --------->\n\n');

        });

        // 当遇到文件不存在、文件编译错误等异常时会触发该事件，该事件不会导致 Webpack 退出。
        compiler.hooks.invalid.tap('test',(stats) => {

            console.log('\n\invalid --------->\n\n');

        });


        /***
         *
         * 输出阶段
         *
         */

        //  所有需要输出的文件已经生成好，询问插件哪些文件需要输出，哪些不需要。
        compiler.hooks.shouldEmit.tap('test',(stats) => {

            console.log('\n\nshouldEmit --------->\n\n');

        });

        // 确定好要输出哪些文件后，执行文件输出，可以在这里获取和修改输出内容。
        compiler.hooks.emit.tap('test',(compilation)=>{

            console.log('\n\nemit  --------->\n\n');

            // 添加新的资源文件
            compilation.assets['filelist.md'] = {
                source: function() {
                  return '我是新插入的资源啊'
                },
                size: function() {
                  return 5555
                }
            }
        
        })

        // 文件输出完毕。
        compiler.hooks.afterEmit.tap('test',(stats) => {

            console.log('\n\afterEmit --------->\n\n');

        });

        // 成功完成一次完成的编译和输出流程。
        compiler.hooks.done.tap('test',(stats) => {

            console.log('\n\ndone --------->\n\n');

        });

        // hasExtractTextPlugin(compiler)

    }

}


module.exports=test